import {_decorator, Component, instantiate, Node, Prefab, Size, Sprite, SpriteFrame, UITransform, Vec3} from 'cc';
import {RandomUtils} from "db://assets/script/common/utils";
import {RandomMapAssets} from "db://assets/script/game/world/random-map-assets";

const {ccclass, property} = _decorator;

@ccclass('BattleField')
export class BattleField extends Component {

    @property(Prefab)
    normalBackground!: Prefab;

    @property(Prefab)
    normalAsset!: Prefab;

    @property(RandomMapAssets)
    randomMapAssets!: RandomMapAssets;

    _groundDic: Array<string> = []

    _maps: Array<OneMap> = []
    _currentOffset = 0
    newMapBlock: boolean = true

    _heightTrims: number = 0
    _widthTrims: number = 0

    _screenHeight: number = 0
    _screenWidth: number = 0

    start() {
        this._screenHeight = this.getComponent(UITransform)!.height
        this._screenWidth = this.getComponent(UITransform)!.width
        this._heightTrims = Math.floor(this._screenHeight / 32) + 1
        this._widthTrims = Math.floor(this._screenWidth / 32) + 1
        this._groundDic[0] = 'textures/maps/base_ground_1/spriteFrame';
        this._groundDic[1] = 'textures/maps/base_ground_2/spriteFrame';
        this._groundDic[2] = 'textures/maps/base_ground_3/spriteFrame';

        this.initNewTotalMap()
    }

    // 初始化完整的地图，默认初始化3张地图。
    initNewTotalMap(): void {
        this.newMapBlock = true
        this._maps.push(this.initOneMap());
        this._maps.push(this.initOneMap());
        this._maps.push(this.initOneMap());
        this._generateMaps()
        this.newMapBlock = false
    }

    // 刷新当前地图所有的展示样式，包括单元格样式、地图物资样式、散落位置
    refreshCurrentMap(nowPos: Vec3) {
        if (this._maps.length > 0) {
            this.newMapBlock = true;
            const oneMap = this._maps[this.inWhichMap(nowPos.y)];
            this._refreshOneMap(oneMap)
            this.newMapBlock = false
        }
    }

    // 实例化一个屏幕的地图
    initOneMap() {
        const totalItems = this._randomWorldAssetIdx()
        let startMap = new OneMap();
        for (let y = 0; y < this._heightTrims; y++) {
            let xTrims: Array<OneCeil> = []
            for (let x = 0; x < this._widthTrims; x++) {
                const idx = (y * this._widthTrims) + x
                let hasItems = totalItems.indexOf(idx) != -1
                xTrims[x] = this._randomOneCeil(hasItems)
                if (hasItems) {
                    startMap.worldAssetCeil.push(xTrims[x])
                }
            }
            startMap.trims[y] = xTrims;
        }
        return startMap;
    }

    // 随机地图物资散落点
    private _randomWorldAssetIdx(): Array<number> {
        const top = Math.floor(this._heightTrims / 2)
        const bottom = this._heightTrims - top
        const topCeil: Array<number> = []
        const bottomCeil: Array<number> = []
        for (let i = 5; i < this._widthTrims * bottom; i++) {
            bottomCeil.push(i)
        }
        for (let i = this._widthTrims * bottom; i < this._widthTrims * (this._heightTrims - 5); i++) {
            topCeil.push(i)
        }
        const totalItems = RandomUtils.randomInPool(topCeil, 15, 20)
        const bottomItems = RandomUtils.randomInPool(bottomCeil, 15, 20)
        totalItems.push(...bottomItems)
        return totalItems
    }


    // 将最底部的地图重新生成并移动到最上方
    moveBottomMap2Top() {
        console.log('move bottom map 2 top')
        const bottomMap = this._maps.shift()!
        this._maps.push(bottomMap)
        this._refreshOneMap(bottomMap)
        this._updateOneMapPosition(bottomMap)
    }

    // 刷新单元格的美术素材
    private _refreshOneMap(oneMap: OneMap) {
        const totalItems = this._randomWorldAssetIdx()
        this._doClearOneMap(oneMap)
        for (let y = 0; y < oneMap.trims.length; y++) {
            const line = oneMap.trims[y]
            for (let x = 0; x < line.length; x++) {
                const idx = y * line.length + x
                const hasItems = totalItems.indexOf(idx) != -1
                line[x].hasItem = hasItems
                line[x].refreshCeilNodeResource(this.randomMapAssets.randomCeil())
                line[x].refreshWorldAssetResource(this.randomMapAssets.randomWorldAssets())
                if (hasItems) {
                    line[x].worldAsset.active = true
                    oneMap.worldAssetCeil.push(line[x])
                }
            }
        }
    }

    // 实例化一个随机单元格
    private _randomOneCeil(hasItems: boolean) {
        const ground = instantiate(this.normalBackground)
        ground.getComponent(Sprite)!.spriteFrame = this.randomMapAssets.randomCeil()
        return new OneCeil(ground, hasItems)
    }


    nearestWorldAssetInMap(nowPos: Vec3): OneCeil | null {
        const idx = this.inWhichMap(nowPos.y)
        let mp = this._maps[idx]
        if (!mp || !mp.worldAssetCeil) {
            return null
        }
        let asset = this._nearestWorldAsset(nowPos, mp.worldAssetCeil)
        if (!asset) {
            mp = this._maps[idx + 1]
            if (!mp || !mp.worldAssetCeil) {
                return null
            }
            asset = this._nearestWorldAsset(nowPos, mp.worldAssetCeil)
        }
        return asset
    }

    private _nearestWorldAsset(nowPos: Vec3, waa: Array<OneCeil>): OneCeil | null {
        let nearestCeil: OneCeil | null = null
        let minDistance: number = Number.MAX_VALUE
        for (let i = 0; i < waa.length; i++) {
            const ceil = waa[i]
            if (ceil.blocked || !ceil.hasItem || ceil.ceilNode.position.y < nowPos.y) {
                continue
            }
            const nowDistance = Vec3.distance(ceil.ceilNode.position, nowPos)
            if (nowDistance > 10 && nowDistance < minDistance) {
                minDistance = nowDistance
                nearestCeil = ceil
            }
        }
        return nearestCeil
    }

    // 生成所有地图。初始化节点并添加
    private _generateMaps() {
        console.log('begin update battle field...')
        for (let i = 0; i < this._maps.length; i++) {
            const oneMap = this._maps[i]
            this._generateOneMap(oneMap)
        }
        console.log('complete update battle field! offset: ', this._currentOffset)
    }

    // 刷新单元格位置
    private _updateOneMapPosition(oneMap: OneMap) {
        for (let y = 0; y < oneMap.trims.length; y++) {
            const oneLine = oneMap.trims[y]
            for (let x = 0; x < oneLine.length; x++) {
                oneLine[x].changePosition(x * 32, this._currentOffset + y * 32)
            }
        }
        for (let oneCeil of oneMap.otherCeil) {
            oneCeil.changePosition(oneCeil.ceilNode.position.x, oneCeil.ceilNode.position.y - oneMap.offset + this._currentOffset)
        }
        oneMap.offset = this._currentOffset
        this._currentOffset += oneMap.trims.length * 32;
    }

    // 生成单个地图。初始化节点并添加
    private _generateOneMap(oneMap: OneMap) {
        oneMap.offset = this._currentOffset
        console.log('generate one map: ', this._currentOffset)
        for (let y = 0; y < oneMap.trims.length; y++) {
            const oneLine = oneMap.trims[y]
            for (let x = -Math.floor(oneLine.length / 2); x < Math.ceil(1.5 * oneLine.length); x++) {
                let oneCeil: OneCeil
                if (x >= 0 && x < oneLine.length) {
                    oneCeil = oneLine[x]
                } else {
                    oneCeil = this._randomOneCeil(false)
                    oneMap.otherCeil.push(oneCeil)
                }
                this.node.addChild(oneCeil.ceilNode)
                const normalAsset = instantiate(this.normalAsset)
                normalAsset.getComponent(Sprite)!.spriteFrame = this.randomMapAssets.randomWorldAssets()
                oneCeil.worldAsset = normalAsset
                oneCeil.changePosition(x * 32, this._currentOffset + y * 32)
                this.node.addChild(normalAsset)
                if (!oneCeil.hasItem) {
                    normalAsset.active = false
                }
            }
        }
        this._currentOffset += oneMap.trims.length * 32
    }

    inWhichMap(y: number): number {
        return this._maps.length - Math.ceil((this._currentOffset - y) / this._screenHeight)
    }

    private _doClearOneMap(clearMap: OneMap) {
        for (let trim of clearMap.trims) {
            for (let oneCeil of trim) {
                oneCeil.worldAsset.active = false
                oneCeil.hasItem = false
            }
        }
        clearMap.worldAssetCeil = []
    }

    onEvent() {

    }

}

class OneMap {
    trims: Array<Array<OneCeil>> = []
    worldAssetCeil: Array<OneCeil> = []
    otherCeil: Array<OneCeil> = []
    offset: number = 0
}

class OneCeil {
    ceilNode: Node
    worldAsset!: Node
    hasItem: boolean = false
    blocked: boolean = false

    constructor(ceilNode: Node, hasItem: boolean) {
        this.ceilNode = ceilNode
        this.hasItem = hasItem
        this.blocked = false
    }

    refreshCeilNodeResource(spriteFrame: SpriteFrame) {
        this.ceilNode.getComponent(Sprite)!.spriteFrame = spriteFrame
    }

    refreshWorldAssetResource(spriteFrame: SpriteFrame) {
        this.worldAsset.getComponent(Sprite)!.spriteFrame = spriteFrame
    }

    changePosition(x: number, y: number) {
        const position = new Vec3(x, y);
        this.ceilNode.setPosition(position)
        if (this.worldAsset) {
            this.worldAsset.setPosition(position)
        }
    }

}

